package com.vmc.strategy;

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.vmc.exception.VMCException;
import com.vmc.model.AbstractTransferDetail;
import com.vmc.model.DetailType;
import com.vmc.model.DownloadTransferProperties;
import com.vmc.model.TVTransferDetail;
import com.vmc.util.GlobalStorageUtility;

public class TransferAction extends AbstractAction<File> {

	static Logger logger = LogManager.getLogger(TransferAction.class);

	public TransferAction() {
	}
	
	@Override
	public boolean performAction(File file) throws VMCException {
		boolean isSuccessful = super.performAction(file);
		if (!isSuccessful) {
			GlobalStorageUtility.getInstance().addUnsuccessfulTransfer(file);
		}

		return isSuccessful;
	}
	
	@Override
	protected boolean performMainAction(File file) throws VMCException {
		
		boolean isSuccessful = false;
		if (GlobalStorageUtility.getInstance().getProperties() != null) {
			logger.info("Performing copy action for " + file.getAbsolutePath());
			DownloadTransferProperties properties = GlobalStorageUtility.getInstance().getProperties();
			
			if (properties.getAllowedExtensions() != null && properties.getTvDestinationDirectory() != null && properties.getMovieDestinationDirectory() != null) {
				if (file.exists()) {
					String extension = FilenameUtils.getExtension(file.getName());
					if (extension != null && !extension.isEmpty() && this.isAllowed(extension, properties.getAllowedExtensions())) {
						isSuccessful = this.transferFile(file, properties);
					}
				}
				else {
					logger.error("The file " + file.getAbsolutePath() + " does not exist.");
				}
			}
			logger.info("Done performing copy action.");
		}
		else {
			logger.error("The property details is invalid.");
		}
		
		return isSuccessful;
	}
	
	private boolean transferFile(File file, DownloadTransferProperties properties) throws VMCException {
		boolean isSuccessful = false;
		try {
			AbstractTransferDetail detail = GlobalStorageUtility.getInstance().getMovieTransferList().getDetail(file.getAbsolutePath());
			
			if (detail == null) {
				detail = TVTransferDetail.Builder.build(file, GlobalStorageUtility.getInstance().getProperties());
			}
			
			if (detail != null) {
				logger.info("Attempting to copy " + detail.getDestinationFilePath());
				attemptDirectoryCreation(detail);
				File destinationFile = new File(detail.getDestinationFilePath());
				if (!destinationFile.exists()) {
					this.attemptMove(file, destinationFile);
					if (destinationFile.exists()) {
						GlobalStorageUtility.getInstance().addCopiedFile(detail);
						isSuccessful = true;
						logger.info("Successfully copied the file.");
					}
				}
				if (detail.getType() == DetailType.Movie) {
					// @TODO: attempt to transfer subtitles and index files
				}
			}
			else {
				logger.error("Detail about the file is invalid.");
			}
		}
		catch(IOException e) {
			throw new VMCException(VMCException.COPY_ERROR, file.getName());
		}
		
		return isSuccessful;
	}
	
	private void attemptMove(File source, File destination) throws IOException, VMCException {
		if (source != null && destination != null) {
			try {
				logger.info("Attempting to move the file " + source.getAbsolutePath() + ".");
				FileUtils.moveFile(source, destination);
			}
			catch (Exception e) {
				logger.error("An error occurred while trying to move the file.");
				logger.info("Attempting copy and delete.");
				this.attempCopyAndDelete(source, destination);
			}
		}
		else {
			throw new VMCException(VMCException.COPY_ERROR, source.getAbsolutePath());
		}
	}
	
	private void attempCopyAndDelete(File source, File destination) throws VMCException {
		if (source != null && destination != null) {
			try {
				logger.info("Attempting to copy the file " + source.getAbsolutePath() + ".");
				FileUtils.copyFile(source, destination, true);
				logger.info("Copy successful.");
				logger.info("Attempting to delete the file " + source.getAbsolutePath() + ".");
				FileUtils.deleteQuietly(source);
			}
			catch (Exception e) {
				throw new VMCException(VMCException.COPY_ERROR, source.getAbsolutePath());
			}
		}
		else {
			throw new VMCException(VMCException.COPY_ERROR, source.getAbsolutePath());
		}
	}
	
	private void attemptDirectoryCreation(AbstractTransferDetail detail) {
		if (detail != null && detail.getLocation() != null) {
			File destinationDirectory = new File(detail.getLocation());
			if (destinationDirectory != null && !destinationDirectory.exists()) {
				createLocation(destinationDirectory);
			}
		}
	}
	
	private boolean createLocation(File location) {
		if (!location.getParentFile().exists()) {
			this.createLocation(location.getParentFile());
		}
		logger.info("Creating " + location.getAbsolutePath() + ".");
		return location.mkdir();
	}
	
	
	private boolean isAllowed(String extension, List<String> allowedExtensions) {
		boolean isAllowed = false;
		
		if (extension != null) {
			for (String allowedExtension : allowedExtensions) {
				if (extension.equalsIgnoreCase(allowedExtension)) {
					isAllowed = true;
					break;
				}
			}
		}
		
		return isAllowed;
	}
}
